#include "bytebuffer.hpp"

using namespace qOS;

//==============================================================================
size_t byteBuffer::checkValidPowerOfTwo(size_t k) noexcept
{
    const size_t r = k;

    if (0U != ((k - 1U) & k)) {
        k--;
        /*cstat -MISRAC++2008-6-5-4 -CERT-INT34-C_a*/
        for (index_t i = 1U;  i < (sizeof(index_t)*8U);  i = static_cast<index_t>(i * 2U)) {
            k = k | static_cast<size_t>(k >> i);
        }
        /*cstat +MISRAC++2008-6-5-4 +CERT-INT34-C_a*/
        k = static_cast<size_t>((k + 1U) >> 1U);
    }

    return (k < r) ? (k * 2U) : k;
}
//==============================================================================
bool byteBuffer::setup(volatile byte_t *pBuffer, const size_t bLength) noexcept
{
    bool retValue = false;

    if ((nullptr != pBuffer) && (length > 0U)) {
        head = 0U;
        tail = 0U;
        buffer = pBuffer;
        length = checkValidPowerOfTwo(bLength);
        retValue = true;
    }

    return retValue;
}
//==============================================================================
bool byteBuffer::put(const byte_t bData) noexcept
{
    bool retValue = false;

    if (!isFull()) {
        buffer[head % length] = bData;
        head = head + 1U;  /*  ++head */
        retValue = true;
    }

    return retValue;
}
//==============================================================================
bool byteBuffer::read(void *dst, const size_t n) noexcept
{
    bool retValue = false;

    if (n > 0U) {
        /*cstat -CERT-EXP36-C_b*/
        byte_t * const pData = static_cast<byte_t*>(dst);
        /*cstat +CERT-EXP36-C_b*/
        for (size_t i = 0U;  i < n;  i++) {
            (void)get(&pData[i]);
        }
        retValue = true;
    }

    return retValue;
}
//==============================================================================
bool byteBuffer::get(byte_t *dst) noexcept
{
    bool retValue = false;

    if (!isEmpty()) {
        const index_t vTail = static_cast<size_t>(tail);
        *dst = buffer[vTail % length];
        tail = tail + 1U;  /* ++tail */
        retValue = true;
    }

    return retValue;
}
//==============================================================================
byte_t byteBuffer::peek(void) const noexcept
{
    const index_t vTail = static_cast<size_t>(tail);
    return static_cast<byte_t>(buffer[vTail % length]);
}
//==============================================================================
bool byteBuffer::isEmpty(void) const noexcept
{
    return (0U == count());
}
//==============================================================================
bool byteBuffer::isFull(void) const noexcept
{
    return (length == count());
}
//==============================================================================
size_t byteBuffer::count(void) const noexcept
{
    const index_t vHead = static_cast<size_t>(head);
    const index_t vTail = static_cast<size_t>(tail);
    return static_cast<size_t>(vHead - vTail);
}
//==============================================================================
